package com.autotest.sync.stf;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.autotest.sync.utils.ADBHelper;
import com.autotest.sync.utils.SystemCmdUtil;
import com.autotest.sync.utils.TimeUtil;

/**
 * 远程操作手机界面
 */
public class MiniTouchUtil {
	private static Logger logger = LogManager.getLogger(MiniTouchUtil.class
			.getSimpleName());
	private static int BUFFER_LEN = 128;
	private static final String MINITOUCH_PORT = "minitouch";
	private String MINITOUCH_FILE = "";
	private BannerMiniTouch mBanner = null;
	private DataOutputStream mOut = null;
	private DataInputStream mInput = null;
	private Socket mSocket = null;
	private DeviceInfo mDevice = null;
	private int mPort = 0;
	private double mWidth = 0;
	private double mHeight = 0;
	private Process mAdbkit;

	public MiniTouchUtil(int port, DeviceInfo device) {
		mPort = port;
		mDevice = device;
		mBanner = new BannerMiniTouch();
		String[] size = mDevice.size.split("x");
		mWidth = Double.parseDouble(size[0]);
		mHeight = Double.parseDouble(size[1]);
		if (Integer.valueOf(mDevice.sdk_version) < 16) {
			MINITOUCH_FILE = Config.MINITOUCH_NOPIE;
		}else {
			MINITOUCH_FILE = Config.MINITOUCH_BIN;
		}
	}
	/**
	 * 启动minitouch服务
	 */
	public void start(){
		killMinitouch();
		forwardPort();
		TimeUtil.sleep(1 *1000);
		startServer();
		TimeUtil.sleep(2 *1000);
		startOperateListener();
		
	}
	
	private void killMinitouch(){
		try {
			String pid = ADBHelper.getAndroidPID(mDevice.serial, "minitouch");
			ADBHelper.killAndroidPID(mDevice.serial, pid);
		} catch (Exception e) {
			logger.warn("minitouch进程关闭异常", e);
		}	
//		int pid = mBanner.getPid();
//		if(pid > 0){
//			ADBHelper.killAndroidPID(mDevice.serial, pid + "");
//		}
	}
	
	public void forwardPort(){
		ADBHelper.forward(mDevice.serial, mPort, MINITOUCH_PORT);
	}

	public void startOperateListener() {
		connectService();
	}

	public void touchDown(String X, String Y) {
		ExecuteTouch(String.format("d 0 %s %s 50\n", X, Y));
	}

	public void touchUp() {
		ExecuteTouch(String.format("u 0\n"));
	}

	public void touchMove(String X, String Y) {
		ExecuteTouch(String.format("m 0 %s %s 50\n", X, Y));
	}
	

	/**
	 * 点击事件
	 * 
	 * @param act
	 */
	public void touchEvent(String act) {
		String[] action = act.split(":");
		if (action.length < 2) {
			return;
		}
		String[] position = null;
		String x = null;
		String y = null;		
		OperateType operateType = OperateType.fromInteger(Integer.parseInt(action[0]));
		if (operateType == null) {
			logger.info(String.format("不支持的操作命令: %s",action[0]));
			return;
		}
		switch (operateType) {
		case TOUCHDOWN:
			position = action[1].split(",");
			x = formatData(Double.parseDouble(position[0])*mWidth, mBanner.getPercentX());
			y = formatData(Double.parseDouble(position[1])*mHeight, mBanner.getPercentY());
			touchDown(x, y);
			break;
		case TOUCHUP:
			touchUp();
			break;
		case TOUCHMOVE:
			position = action[1].split(",");
			x = formatData(Double.parseDouble(position[0])*mWidth, mBanner.getPercentX());
			y = formatData(Double.parseDouble(position[1])*mHeight, mBanner.getPercentY());
			touchMove(x, y);
			break;
		case ADBCMD:
			// ClickKeycode((int)action[1]);
			execAdbCmd(action[1]);
			break;
		case SLEEP:
			TimeUtil.sleep(Long.parseLong(action[1]));
			break;
		case SET_TEXT:
			setText(action[1]);
			break;
		default:
			break;
		}
	}
	
	private String formatData(double data1, double data2){
		return String.valueOf(new DecimalFormat("0").format(data1/data2));
	}
	
	/**
	 * 执行touch cmd
	 * @param touchCommand
	 */
	public void ExecuteTouch(String touchCommand) {
//		System.out.println(touchCommand);
		byte[] inbuff = (touchCommand + "c\n").getBytes();
		try {
			if (mOut != null) {
				mOut.write(inbuff);
				mOut.flush();
			}
		} catch (IOException e) {
			logger.error(e);
		}
	}
	
	
	/**
	 * 执行input keycode
	 * @param keycode
	 */
	private void execAdbCmd(String keycode){
		String cmd = String.format("adb -s %s shell input keyevent %s", mDevice.serial, keycode);
		ADBHelper.exec(cmd, 5);
	}
	
	/**
	 * 执行输入文本
	 * @param keycode
	 */
	private void setText(String content){
		String cmd = String.format("adb -s %s shell input text %s", mDevice.serial, content);
		ADBHelper.exec(cmd, 5);
	}

	/**
	 * 设置标题，大小，压力
	 * @param buffer
	 */
	private void parseBanner(String buffer) {
		String[] isoString = buffer.split("\\s+");
		mBanner.setMaxContacts(Integer.parseInt(isoString[3]));
		mBanner.setMaxX(Integer.parseInt(isoString[4]));
		mBanner.setMaxY(Integer.parseInt(isoString[5]));
		mBanner.setMaxPressure(Integer.parseInt(isoString[6]));
		mBanner.setPid(Integer.parseInt(isoString[8]));
		mBanner.setPercentX(mWidth / mBanner.getMaxX());
		mBanner.setPercentY(mHeight / mBanner.getMaxY());
	}
	
	/**
	 * 连接minitouch服务
	 */
	private void connectService() {
		try {
			mSocket = new Socket("127.0.0.1", mPort);
			mInput = new DataInputStream(mSocket.getInputStream());
			mOut = new DataOutputStream(mSocket.getOutputStream());
			long bTime = System.currentTimeMillis();
			while(mInput.available() <= 0){
				if(System.currentTimeMillis() - bTime > 20 * 1000){
					return;
				}
			}
			int realLen = -1;
			byte[] buffer = new byte[BUFFER_LEN];
			realLen = mInput.read(buffer);
			if (buffer.length != realLen) {
				buffer = ArrayUtils.subarray(buffer, 0, realLen);
			}
			parseBanner(new String(buffer));
			logger.debug(mBanner.toString());
		} catch (UnknownHostException e) {
			logger.error(e);
		} catch (IOException e) {
			logger.error(e);
		}
	}
	
	/**
	 * 关闭所有资源
	 */
	public void close() {
		IOUtils.closeQuietly(mInput);
		IOUtils.closeQuietly(mOut);
		IOUtils.closeQuietly(mSocket);
		ADBHelper.removeForward(mPort);
		killMinitouch();
		if (mAdbkit != null){
			if(mAdbkit.isAlive()){
				mAdbkit.destroy();
			}
		}
	}
	
	private void startServer(){
		String startCmd = String.format(Config.MINITOUCH_START_COMMAND, MINITOUCH_FILE);
		SystemCmdUtil.execNoStream(String.format("adb -s %s shell %s", mDevice.serial, startCmd));
	}
}
